<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>知识库前端demo</title>
    <script src="lib/vue/vue.min.js"></script>
    <style>
        body {
            font-family: 'Arial', sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }

        .container {
            background: #f9f9f9;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }

        h1 {
            color: #333;
            text-align: center;
        }

        .input-section, .output-section {
            margin-bottom: 20px;
        }

        label {
            display: block;
            margin-bottom: 8px;
            font-weight: bold;
        }

        input, textarea {
            width: 100%;
            padding: 10px;
            margin-bottom: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            box-sizing: border-box;
        }

        button {
            background-color: #4CAF50;
            color: white;
            padding: 10px 15px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
        }

        button:hover {
            background-color: #45a049;
        }

        .output-section textarea {
            height: 150px;
            resize: vertical;
        }

        .status {
            color: #666;
            font-size: 14px;
            margin-top: 10px;
        }
    </style>
</head>
<body>
<div id="app" class="container">
    <h1>知识库前端demo</h1>

    <div class="input-section">
        <label for="inputText">输入问题:</label>
        <input
                type="text"
                id="inputText"
                v-model="inputText"
                placeholder="输入问题"
        >
        <button @click="splitText">GET</button>
        <button @click="splitText_post">POST</button>
    </div>

    <div class="output-section">
        <label for="outputText">大模型回答:</label>
        <textarea
                id="outputText"
                v-model="outputText"
                placeholder="答案显示"
                readonly
        ></textarea>
        <div class="status">{{ statusMessage }}</div>
    </div>
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            inputText: '',
            outputText: '',
            statusMessage: '准备就绪',
            eventSource: null,
            connectionClosed: false
        },
        methods: {
            splitText() {
                if (!this.inputText.trim()) {
                    this.statusMessage = '请输入文本';
                    return;
                }

                // 重置输出、状态和标志
                this.outputText = '';
                this.statusMessage = '正在回答...';
                this.connectionClosed = false;

                // 创建或关闭现有的EventSource
                if (this.eventSource) {
                    this.eventSource.close();
                }

                // 构建SSE URL并添加查询参数
                // const url = `/knowledge_base/answer?query=${encodeURIComponent(this.inputText)}`;
                // const url = `http://192.168.3.201:8080/knowledge_base/answer?query=${encodeURIComponent(this.inputText)}`
                const url = `http://localhost:8080/knowledge_base/answer?query=${encodeURIComponent(this.inputText)}`
                // 创建新的EventSource
                this.eventSource = new EventSource(url);

                // 处理接收到的消息
                this.eventSource.onmessage = (event) => {
                    // 检查是否是结束消息
                    if (event.data === '[DONE]') {
                        this.connectionClosed = true;
                        this.eventSource.close();
                        this.statusMessage = '回答完成';
                        return;
                    }
                    tmp_data = JSON.parse(event.data)
                    d = tmp_data.content
                    this.outputText += d;
                };

                // 处理连接打开事件
                this.eventSource.onopen = () => {
                    this.statusMessage = '正在接收字符...';
                };

                // 处理错误事件
                this.eventSource.onerror = (error) => {
                    // 如果不是正常关闭，才显示错误
                    if (!this.connectionClosed) {
                        this.statusMessage = '连接错误';
                        console.error('EventSource failed:', error);
                    }
                    this.eventSource.close();
                };

                // 处理连接关闭
                this.eventSource.onclose = () => {
                    if (!this.connectionClosed) {
                        this.statusMessage = '连接已关闭';
                    }
                };
            },
            splitText_post() {
                if (!this.inputText.trim()) {
                    this.statusMessage = '请输入文本';
                    return;
                }

                this.outputText = '';
                this.statusMessage = '正在回答...';
                this.connectionClosed = false;

                // 使用fetch API发送POST请求
                // fetch('http://192.168.3.201:8080/knowledge_base/answer', {
                fetch('http://localhost:8080/knowledge_base/answer', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'Access-Control-Allow-Origin': '*',
                    },
                    body: JSON.stringify({query: this.inputText})
                })
                    .then(response => {
                        if (!response.ok) {
                            throw new Error(`HTTP error! status: ${response.status}`);
                        }

                        // 读取响应流
                        const reader = response.body.getReader();
                        const decoder = new TextDecoder();

                        const read = () => {
                            reader.read().then(({done, value}) => {
                                if (done) {
                                    this.connectionClosed = true;
                                    this.statusMessage = '回答完成';
                                    return;
                                }

                                // 解析SSE消息
                                const chunk = decoder.decode(value);
                                const messages = chunk.split('\n\n');

                                messages.forEach(message => {
                                    if (message.startsWith('data: ')) {
                                        const data = message.substring(6);
                                        if (data === '[DONE]') {
                                            this.connectionClosed = true;
                                            this.statusMessage = '回答完成';
                                        } else {
                                            tmp_data = JSON.parse(data)
                                            d = tmp_data.content
                                            this.outputText += d;
                                        }
                                    }
                                });

                                read(); // 继续读取下一个块
                            }).catch(error => {
                                if (!this.connectionClosed) {
                                    this.statusMessage = '连接错误';
                                    console.error('读取流失败:', error);
                                }
                            });
                        };

                        read(); // 开始读取流
                    })
                    .catch(error => {
                        if (!this.connectionClosed) {
                            this.statusMessage = '连接错误';
                            console.error('Fetch error:', error);
                        }
                    });
            }
        },
        beforeDestroy() {
            // 组件销毁前关闭EventSource连接
            if (this.eventSource) {
                this.eventSource.close();
            }
        }
    });
</script>
</body>
</html>